package logic

import (
	"github.com/gogap/logs"
	"sync"
	"yundian/internel/app/dao"
	"yundian/internel/app/models/statistics"
)

// 用户数据分析 - 超级管理员、员工用户、商户 不统计
type TaskStatisticsUserLogic struct {
}

func NewTaskStatisticsUserLogic() *TaskStatisticsUserLogic {
	return &TaskStatisticsUserLogic{}
}

// 动销用户数据分析
func (t *TaskStatisticsUserLogic) StatisticsByTypeByHaveOrders(dateList []string) ( r bool) {
	for _, d := range dateList {
		var tempOrder, tempDividends, tempUserRel bool
		var tempWg sync.WaitGroup
		tempWg.Add(3)
		go func() {
			defer tempWg.Done()
			tempOrder = dao.NewStatisticsDao().InsertOrderToTemp(d).Unwrap().(bool)
		}()
		go func() {
			defer tempWg.Done()
			tempDividends = dao.NewStatisticsDao().InsertDividendsToTemp(d).Unwrap().(bool)
		}()
		go func() {
			defer tempWg.Done()
			tempUserRel = dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(d).Unwrap().(bool)
		}()
		tempWg.Wait()

		if tempOrder && tempDividends && tempUserRel {
			ids := dao.NewStatisticsDao().GetUserIdsByOrders(d).Unwrap().([]int) // 动销用户列表
			maxGoroutine := 4 // 开启协程的大小
			var pool chan struct{}
			pool = make(chan struct{}, maxGoroutine) // 协程池
			var wg sync.WaitGroup
			for _,id := range ids {
				wg.Add(1)
				pool <- struct{}{}
				go func(str string, userId int) {
					defer wg.Done()
					defer func() {
						<- pool
					}()
					t.OrderAndIncomeStatistics(str, userId)
				}(d, id)
			}
			wg.Wait()
			dao.NewStatisticsDao().DeleteTempTable(d) // 删除临时表
			logs.Info("日期", d, "缓存表已清除")
		} else {
			logs.Info("日期", d, "缓存表生成失败")
		}
	}
	//if len(dateList) <= 4 {
	//	for _, d := range dateList {
	//		if ok := dao.NewStatisticsDao().InsertOrderToTemp(d).Unwrap().(bool); ok { // 订单临时表
	//			if ok := dao.NewStatisticsDao().InsertDividendsToTemp(d).Unwrap().(bool); ok { // 分红临时表
	//				if ok := dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(d).Unwrap().(bool); ok { // 用户关联表-临时
	//					ids := dao.NewStatisticsDao().GetUserIdsByOrders(d).Unwrap().([]int) // 动销用户列表
	//					maxGoroutine := 4 // 开启协程的大小
	//					var pool chan struct{}
	//					pool = make(chan struct{}, maxGoroutine) // 协程池
	//					var wg sync.WaitGroup
	//					for _,id := range ids {
	//						wg.Add(1)
	//						pool <- struct{}{}
	//						go func(str string, userId int) {
	//							defer wg.Done()
	//							defer func() {
	//								<- pool
	//							}()
	//							t.OrderAndIncomeStatistics(str, userId)
	//						}(d, id)
	//					}
	//					wg.Wait()
	//					dao.NewStatisticsDao().DeleteTempTable(d) // 删除临时表
	//				}
	//			}
	//		}
	//	}
	//} else {
	//	maxGoroutine := 2
	//	var pool chan struct{}
	//	pool = make(chan struct{}, maxGoroutine)
	//	var wg sync.WaitGroup
	//	for _, dateStr := range dateList {
	//		wg.Add(1)
	//		pool <- struct{}{}
	//		go func(d string) {
	//			defer wg.Done()
	//			defer func() {
	//				<- pool
	//			}()
	//			if ok := dao.NewStatisticsDao().InsertOrderToTemp(d).Unwrap().(bool); ok { // 订单临时表
	//				if ok := dao.NewStatisticsDao().InsertDividendsToTemp(d).Unwrap().(bool); ok { // 分红临时表
	//					if ok := dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(d).Unwrap().(bool); ok { // 用户关联表-临时
	//						ids := dao.NewStatisticsDao().GetUserIdsByOrders(d).Unwrap().([]int) // 动销用户列表
	//						maxGoroutine := 4 // 开启协程的大小
	//						var pool chan struct{}
	//						pool = make(chan struct{}, maxGoroutine) // 协程池
	//						var wg sync.WaitGroup
	//						for _,id := range ids {
	//							wg.Add(1)
	//							pool <- struct{}{}
	//							go func(str string, userId int) {
	//								defer wg.Done()
	//								defer func() {
	//									<- pool
	//								}()
	//								t.OrderAndIncomeStatistics(str, userId)
	//							}(d, id)
	//						}
	//						wg.Wait()
	//						dao.NewStatisticsDao().DeleteTempTable(d) // 删除临时表
	//					}
	//				}
	//			}
	//		}(dateStr)
	//	}
	//	wg.Wait()
	//}
	return true
}

// 未动销用户数据分析
func (t *TaskStatisticsUserLogic) StatisticsByTypeByNoHaveOrders(dateStr string) ( r bool) {
	var tempOrder, tempDividends, tempUserRel bool
	var tempWg sync.WaitGroup
	tempWg.Add(3)
	go func() {
		defer tempWg.Done()
		tempOrder = dao.NewStatisticsDao().InsertOrderToTemp(dateStr).Unwrap().(bool)
	}()
	go func() {
		defer tempWg.Done()
		tempDividends = dao.NewStatisticsDao().InsertDividendsToTemp(dateStr).Unwrap().(bool)
	}()
	go func() {
		defer tempWg.Done()
		tempUserRel = dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(dateStr).Unwrap().(bool)
	}()
	tempWg.Wait()

	if tempOrder && tempDividends && tempUserRel {
		ids := dao.NewStatisticsDao().GetUserIdsByOrders(dateStr).Unwrap().([]int) // 动销用户列表
		userIds := dao.NewStatisticsDao().GetOtherUserIdsByIds(ids, dateStr).Unwrap().([]int) // 未动销用户数
		maxGoroutine := 4 // 开启协程的大小
		var pool chan struct{}
		pool = make(chan struct{}, maxGoroutine) // 协程池
		var wg sync.WaitGroup
		for _,id := range userIds {
			wg.Add(1)
			pool <- struct{}{}
			go func(str string, userId int) {
				defer wg.Done()
				defer func() {
					<- pool
				}()
				t.OrderAndIncomeStatisticsOther(str, userId)
			}(dateStr, id)
		}
		wg.Wait()
		dao.NewStatisticsDao().DeleteTempTable(dateStr)
		logs.Info("缓存表已清除")
	} else {
		logs.Info("缓存表生成失败")
	}

	//if ok := dao.NewStatisticsDao().InsertOrderToTemp(dateStr).Unwrap().(bool); ok { // 订单临时表
	//	if ok := dao.NewStatisticsDao().InsertDividendsToTemp(dateStr).Unwrap().(bool); ok { // 分红临时表
	//		if ok := dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(dateStr).Unwrap().(bool); ok { // 用户关联表-临时
	//			ids := dao.NewStatisticsDao().GetUserIdsByOrders(dateStr).Unwrap().([]int) // 动销用户列表
	//			userIds := dao.NewStatisticsDao().GetOtherUserIdsByIds(ids, dateStr).Unwrap().([]int) // 未动销用户数
	//			maxGoroutine := 4 // 开启协程的大小
	//			var pool chan struct{}
	//			pool = make(chan struct{}, maxGoroutine) // 协程池
	//			var wg sync.WaitGroup
	//			for _,id := range userIds {
	//				wg.Add(1)
	//				pool <- struct{}{}
	//				go func(str string, userId int) {
	//					defer wg.Done()
	//					defer func() {
	//						<- pool
	//					}()
	//					t.OrderAndIncomeStatisticsOther(str, userId)
	//				}(dateStr, id)
	//			}
	//			wg.Wait()
	//			dao.NewStatisticsDao().DeleteTempTable(dateStr)
	//		}
	//	}
	//}
	return true
}

// 单个用户数据分析
func (t *TaskStatisticsUserLogic) StatisticsByTypeByUserId(dateStr string, userId int) ( r bool) {
	if ok := dao.NewStatisticsDao().InsertOrderToTemp(dateStr).Unwrap().(bool); ok {
		if ok := dao.NewStatisticsDao().InsertDividendsToTemp(dateStr).Unwrap().(bool); ok {
			if ok := dao.NewStatisticsDao().InsertOrdersUserRelevancyToTemp(dateStr).Unwrap().(bool); ok {
				if ok := t.OrderAndIncomeStatistics(dateStr, userId); ok {
					dao.NewStatisticsDao().DeleteTempTable(dateStr) // 删除临时表
					return true
				}
			}
		}
	}
	return false
}

// 动销用户数据分析
func (t *TaskStatisticsUserLogic) OrderAndIncomeStatistics(dateStr string, id int) (ok bool) {
	m := &statistics.StatisticsUserModel{}
	var mEnd, mComplete, mCancel, mSy dao.CountSettlement
	var mAllDraw, mDraw, mNoDraw, mSmallDraw, mcNodraw, cNodraw dao.CountSettlement
	var totalDevices, totalIncome int64
	var directUsers, directPlaces, totalUsers, totalPlaces, userIds []int
	var wx, qrcode, qrcodeWait, qrcodeSuccess, qrcodeFail dao.CountSettlement
	var placeSales int64

	userIds = append(userIds, id)

	var w sync.WaitGroup
	w.Add(4)
	go func() {
		defer w.Done()
		directUsers = dao.NewStatisticsDao().CountUsersByParentId(userIds, dateStr).Unwrap().([]int) // 直属团队数
		directPlaces = dao.NewStatisticsDao().CountPlacesByUserId(id, dateStr).Unwrap().([]int) // 直属门店数
		totalUsers = t.GetTotalTeams(id, dateStr) // 团队总数
		totalPlaces = dao.NewStatisticsDao().CountPlacesByUserIds(totalUsers, dateStr).Unwrap().([]int) // 门店总数
		totalDevices = dao.NewStatisticsDao().CountDevicesByPlaceIds(totalPlaces).Unwrap().(int64) // 设备总数
	}()
	go func() {
		defer w.Done()
		mEnd = dao.NewStatisticsDao().QueryUserTotalOrderByState(0, id, dateStr).Unwrap().(dao.CountSettlement)
		mComplete = dao.NewStatisticsDao().QueryUserTotalOrderByState(5, id, dateStr).Unwrap().(dao.CountSettlement)
		mCancel = dao.NewStatisticsDao().QueryUserTotalOrderByState(3, id, dateStr).Unwrap().(dao.CountSettlement)
		mSy = dao.NewStatisticsDao().QueryUserTotalOrderByState(7, id, dateStr).Unwrap().(dao.CountSettlement)

		totalIncome = dao.NewStatisticsDao().QueryUserTotalIncomeByUserId(id, dateStr).Unwrap().(int64)
	}()
	go func() {
		defer w.Done()
		mAllDraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(4, 5, id, dateStr).Unwrap().(dao.CountSettlement)
		mDraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(1, 5, id, dateStr).Unwrap().(dao.CountSettlement)
		mNoDraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(2, 0, id, dateStr).Unwrap().(dao.CountSettlement)
		mSmallDraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(3, 5, id, dateStr).Unwrap().(dao.CountSettlement)
		mcNodraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(2, 5, id, dateStr).Unwrap().(dao.CountSettlement)
		cNodraw = dao.NewStatisticsDao().QueryUserTotalOrderByDraw(2, 3, id, dateStr).Unwrap().(dao.CountSettlement)
	}()
	go func() {
		defer w.Done()
		// 获取门店动销
		placeSales = dao.NewStatisticsDao().QueryPlaceSalesByUserId(dateStr, id).Unwrap().(int64)
		wx = t.QueryTotalCashLog(dateStr, 0, 0, id)
		qrcode = t.QueryTotalCashLog(dateStr, 2, 0, id)
		qrcodeWait = t.QueryTotalCashLog(dateStr, 2, 1, id)
		qrcodeSuccess = t.QueryTotalCashLog(dateStr, 2, 2, id)
		qrcodeFail = t.QueryTotalCashLog(dateStr, 2, 3, id)
	}()
	w.Wait()

	m.DateStr = dateStr // 日期
	m.UserId = int64(id) // 用户ID

	m.TotalTeam = len(totalUsers) // 团队总数
	m.TotalPlace = len(totalPlaces) // 门店总数
	m.TotalDirectPlace = len(directPlaces)  // 直属下级
	m.TotalDirectTeam = len(directUsers)  // 直属门店
	m.TotalDevices = totalDevices // 设备总数

	m.TotalOrders = mEnd.Total          // 当天订单数
	m.TotalComplete = mComplete.Total   // 当天完成的订单数
	m.TotalCancel = mCancel.Total       // 当天撤销的订单数
	m.TotalSy = mSy.Total               // 当天守约的订单数
	m.TotalCompleteNodraw = mcNodraw.Total
	m.TotalCancelNodraw = cNodraw.Total

	m.TotalAllDraw = mAllDraw.Total     // 总抽单数
	m.TotalDraw = mDraw.Total           // 普通 抽单数
	m.TotalSmalldraw = mSmallDraw.Total
	m.TotalNodraw = mNoDraw.Total       // 未抽单数

	m.TotalIncome = totalIncome                 // 用户收益

	m.PlaceSales = placeSales // 门店动销数

	m.SettlementTotal = mEnd.Money
	m.SettlementComplete = mComplete.Money
	m.SettlementCancel = mCancel.Money
	m.SettlementNormalTotal = mcNodraw.Money
	m.SettlementCancelNodraw = cNodraw.Money

	m.SettlementAlldraw = mAllDraw.Money
	m.SettlementDraw = mDraw.Money
	m.SettlementNodraw = mNoDraw.Money
	m.SettlementSmalldraw = mSmallDraw.Money

	m.WeixinTotal = wx.Total
	m.WeixinMoney = wx.Money
	m.QrcodeTotal = qrcode.Total
	m.QrcodeSuccessTotal = qrcodeSuccess.Total
	m.QrcodeSuccessMoney = qrcodeSuccess.Money
	m.QrcodeWaitTotal = qrcodeWait.Total
	m.QrcodeWaitMoney = qrcodeWait.Money
	m.CashFailedTotal = qrcodeFail.Total
	m.CashFailedMoney = qrcodeFail.Money

	ok = dao.NewStatisticsDao().InsertStatisticsUser(m).Unwrap().(bool)
	return
}

// 未动销用户数据分析
func (t *TaskStatisticsUserLogic) OrderAndIncomeStatisticsOther(dateStr string, id int) (ok bool) {
	m := &statistics.StatisticsUserModel{}
	var totalDevices int64
	var directUsers, directPlaces, totalUsers, totalPlaces, userIds []int
	var wx, qrcode, qrcodeWait, qrcodeSuccess, qrcodeFail dao.CountSettlement
	userIds = append(userIds, id)

	var w sync.WaitGroup
	w.Add(3)
	go func() {
		defer w.Done()
		directUsers = dao.NewStatisticsDao().CountUsersByParentId(userIds, dateStr).Unwrap().([]int) // 直属团队数
		directPlaces = dao.NewStatisticsDao().CountPlacesByUserId(id, dateStr).Unwrap().([]int) // 直属门店数
	}()
	go func() {
		defer w.Done()
		totalUsers = t.GetTotalTeams(id, dateStr) // 团队总数
		totalPlaces = dao.NewStatisticsDao().CountPlacesByUserIds(totalUsers, dateStr).Unwrap().([]int) // 门店总数
		totalDevices = dao.NewStatisticsDao().CountDevicesByPlaceIds(totalPlaces).Unwrap().(int64) // 设备总数
	}()
	go func() {
		defer w.Done()
		wx = t.QueryTotalCashLog(dateStr, 0, 0, id)
		qrcode = t.QueryTotalCashLog(dateStr, 2, 0, id)
		qrcodeWait = t.QueryTotalCashLog(dateStr, 2, 1, id)
		qrcodeSuccess = t.QueryTotalCashLog(dateStr, 2, 2, id)
		qrcodeFail = t.QueryTotalCashLog(dateStr, 2, 3, id)
	}()
	w.Wait()

	m.DateStr = dateStr // 日期
	m.UserId = int64(id) // 用户ID

	m.TotalTeam = len(totalUsers) // 团队总数
	m.TotalPlace = len(totalPlaces) // 门店总数
	m.TotalDirectPlace = len(directPlaces)  // 直属下级
	m.TotalDirectTeam = len(directUsers)  // 直属门店
	m.TotalDevices = totalDevices // 设备总数

	m.TotalOrders = 0          // 当天订单数
	m.TotalComplete = 0   // 当天完成的订单数
	m.TotalCancel = 0       // 当天撤销的订单数
	m.TotalSy = 0               // 当天守约的订单数
	m.TotalCancelNodraw = 0
	m.TotalCompleteNodraw = 0

	m.TotalAllDraw = 0     // 总抽单数
	m.TotalDraw = 0           // 普通 抽单数
	m.TotalSmalldraw = 0
	m.TotalNodraw = 0       // 未抽单数

	m.TotalIncome = 0                   // 用户收益

	m.SettlementTotal = 0
	m.SettlementComplete = 0
	m.SettlementCancel = 0
	m.SettlementNormalTotal = 0
	m.SettlementCancelNodraw = 0

	m.SettlementAlldraw = 0
	m.SettlementDraw = 0
	m.SettlementNodraw = 0
	m.SettlementSmalldraw = 0

	m.WeixinTotal = wx.Total
	m.WeixinMoney = wx.Money
	m.QrcodeTotal = qrcode.Total
	m.QrcodeSuccessTotal = qrcodeSuccess.Total
	m.QrcodeSuccessMoney = qrcodeSuccess.Money
	m.QrcodeWaitTotal = qrcodeWait.Total
	m.QrcodeWaitMoney = qrcodeWait.Money
	m.CashFailedTotal = qrcodeFail.Total
	m.CashFailedMoney = qrcodeFail.Money

	ok = dao.NewStatisticsDao().InsertStatisticsUser(m).Unwrap().(bool)
	return
}

// 获取总团队人数
func (t *TaskStatisticsUserLogic) GetTotalTeams(id int, dateStr string) []int {
	isLoop := true
	var userIds, ids []int
	ids = append(ids, id)
	for isLoop {
		tempUserIds := dao.NewStatisticsDao().CountUsersByParentId(ids, dateStr).Unwrap().([]int)
		if len(tempUserIds) == 0 {
			isLoop = false
		} else {
			userIds = append(userIds, tempUserIds...)
			ids = tempUserIds
		}
	}
	return userIds
}

// QueryTotalCashLog
func (t *TaskStatisticsUserLogic) QueryTotalCashLog(dateStr string, transferType, state, id int) dao.CountSettlement {
	cashLog := dao.NewStatisticsDao().QueryUserTotalCashLog(dateStr, transferType, state, id).Unwrap().(dao.CountSettlement) // 创建时间订单总数
	return cashLog
}
